package com.cdks.wuxiu.common.config;

import com.alibaba.fastjson.support.spring.GenericFastJsonRedisSerializer;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;

import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.Duration;

/**
 * Redis 配置类
 */
@Configuration
public class RedisConfig {
    @Value("${spring.redis.host}")
    private String host;
    @Value("${spring.redis.port}")
    private int port;
    @Value("${spring.redis.password}")
    private String password;
    @Value("${spring.redis.timeout}")
    private Duration timeout;
    @Value("${spring.redis.lettuce.pool.max-active}")
    private int maxActive;
    @Value("${spring.redis.lettuce.pool.max-idle}")
    private int maxIdle;
    @Value("${spring.redis.lettuce.pool.min-idle}")
    private int minIdle;

    @Bean(name = "redisTemplate00")
    public RedisTemplate<String, String> redisTemplate00() {
        return initRedisTemplate(0);
    }

    @Bean(name = "redisTemplate01")
    public RedisTemplate<String, String> redisTemplate01() {
        return initRedisTemplate(1);
    }

    @Bean(name = "redisTemplate02")
    public RedisTemplate<String, String> redisTemplate02() {
        return initRedisTemplate(2);
    }

    @Bean(name = "redisTemplate03")
    public RedisTemplate<String, String> redisTemplate03() {
        return initRedisTemplate(3);
    }

    @Bean(name = "redisTemplate04")
    public RedisTemplate<String, String> redisTemplate04() {
        return initRedisTemplate(4);
    }

    @Bean(name = "redisTemplate05")
    public RedisTemplate<String, String> redisTemplate05() {
        return initRedisTemplate(5);
    }

    @Bean(name = "redisTemplate06")
    public RedisTemplate<String, String> redisTemplate06() {
        return initRedisTemplate(6);
    }

    @Bean(name = "redisTemplate07")
    public RedisTemplate<String, String> redisTemplate07() {
        return initRedisTemplate(7);
    }

    @Bean(name = "redisTemplate08")
    public RedisTemplate<String, String> redisTemplate08() {
        return initRedisTemplate(8);
    }

    @Bean(name = "redisTemplate09")
    public RedisTemplate<String, String> redisTemplate09() {
        return initRedisTemplate(9);
    }

    @Bean(name = "redisTemplate10")
    public RedisTemplate<String, String> redisTemplate10() {
        return initRedisTemplate(10);
    }

    @Bean(name = "redisTemplate11")
    public RedisTemplate<String, String> redisTemplate11() {
        return initRedisTemplate(11);
    }

    @Bean(name = "redisTemplate12")
    public RedisTemplate<String, String> redisTemplate12() {
        return initRedisTemplate(12);
    }

    @Bean(name = "redisTemplate13")
    public RedisTemplate<String, String> redisTemplate13() {
        return initRedisTemplate(13);
    }

    @Bean(name = "redisTemplate14")
    public RedisTemplate<String, String> redisTemplate14() {
        return initRedisTemplate(14);
    }

    @Bean(name = "redisTemplate15")
    public RedisTemplate<String, String> redisTemplate15() {
        return initRedisTemplate(15);
    }

    /**
     * 初始化RedisTemplate
     */
    public RedisTemplate<String, String> initRedisTemplate(Integer db) {
        // 基本配置
        RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration();
        configuration.setHostName(host);
        configuration.setPort(port);
        configuration.setPassword(password);
        configuration.setDatabase(db);
        
        // 连接池通用配置
        GenericObjectPoolConfig<LettucePoolingClientConfiguration> genericObjectPoolConfig = new GenericObjectPoolConfig<>();
        genericObjectPoolConfig.setMaxTotal(maxActive);
        genericObjectPoolConfig.setMaxIdle(maxIdle);
        genericObjectPoolConfig.setMinIdle(minIdle);

        // LettucePool
        LettucePoolingClientConfiguration.LettucePoolingClientConfigurationBuilder builder = LettucePoolingClientConfiguration.builder();
        builder.poolConfig(genericObjectPoolConfig);
        builder.commandTimeout(timeout);
        LettuceConnectionFactory connectionFactory = new LettuceConnectionFactory(configuration, builder.build());
        connectionFactory.afterPropertiesSet();

        // RedisTemplate
        RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        RedisSerializer<Object> fastJsonRedisSerializer = new GenericFastJsonRedisSerializer();
       
        redisTemplate.setKeySerializer(stringRedisSerializer);
        redisTemplate.setValueSerializer(stringRedisSerializer);
        redisTemplate.setHashKeySerializer(stringRedisSerializer);
        redisTemplate.setHashValueSerializer(stringRedisSerializer);
        redisTemplate.setConnectionFactory(connectionFactory);
        redisTemplate.setEnableTransactionSupport(true);
        redisTemplate.afterPropertiesSet();

        return redisTemplate;
    }

    @Bean
    public RedisTemplate<Object, ?> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        RedisSerializer<Object> fastJsonRedisSerializer = new GenericFastJsonRedisSerializer();
        
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        redisTemplate.setKeySerializer(stringRedisSerializer);
        redisTemplate.setValueSerializer(stringRedisSerializer);
        redisTemplate.setHashKeySerializer(stringRedisSerializer);
        redisTemplate.setHashValueSerializer(stringRedisSerializer);
        redisTemplate.setEnableTransactionSupport(true);
        redisTemplate.afterPropertiesSet();

        return redisTemplate;
    }
}
